package com.ruoyi.algorithm.config;

import com.ruoyi.algorithm.util.harbor.UnCompress;
import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.command.DockerCmdExecFactory;
import com.github.dockerjava.api.command.LoadImageCmd;
import com.github.dockerjava.api.model.AuthConfig;
import com.github.dockerjava.api.model.PushResponseItem;
import com.github.dockerjava.core.DefaultDockerClientConfig;
import com.github.dockerjava.core.DockerClientBuilder;
import com.github.dockerjava.core.DockerClientConfig;
import com.github.dockerjava.core.command.PushImageResultCallback;
import com.github.dockerjava.jaxrs.JerseyDockerCmdExecFactory;
import org.apache.commons.lang.StringUtils;

import java.io.*;
import java.util.logging.Logger;

/**
 * @author dyk
 * @date 2021/7/6 14:44
 * @description
 */
public class UploadImage {

    private String tarPath; // tar包临时存放路径

    private final static Logger logger = Logger.getLogger(UploadImage.class.getName());

    private String dockerHost;

    private String harborAddress;

    private String harborUserName;

    private String harborPassword;

    private InputStream inputStream;

    private String originalImageName;

    private String imageName;

    public UploadImage(String harborAddress, String dockerHost, String harborUserName, String harborPassword,
                       String imageName, InputStream inputStream, String tarPath) throws IOException {
        super();
        this.imageName = imageName;
        this.dockerHost = dockerHost;
        this.harborAddress = harborAddress;
        this.harborUserName = harborUserName;
        this.harborPassword = harborPassword;
        this.inputStream = inputStream;
        this.tarPath = tarPath;
        BufferedInputStream bis = new BufferedInputStream(inputStream);

        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(tarPath));


        byte[] bytes = new byte[1024 * 8];
        int len;
        while ((len = bis.read(bytes)) != -1) {
            bos.write(bytes, 0, len);
        }
        if (bos != null) {
            bos.close();
        }
    }

    public boolean uploadResp() {
        boolean result;
        long beginTime = System.currentTimeMillis();
        if (StringUtils.isEmpty(harborUserName)) {
            harborUserName = null;
        }
        if (StringUtils.isEmpty(harborPassword)) {
            harborPassword = null;
        }

        AuthConfig authConfig = new AuthConfig()
                .withUsername(harborUserName)
                .withPassword(harborPassword)
                .withRegistryAddress(harborAddress);

        DockerClientConfig dockerClientConfig = DefaultDockerClientConfig.createDefaultConfigBuilder()
                .withDockerHost(dockerHost)
                .build();

        DockerCmdExecFactory dockerCmdExecFactory = new JerseyDockerCmdExecFactory().withReadTimeout(600000)
                .withConnectTimeout(10000)
                .withMaxTotalConnections(100)
                .withMaxPerRouteConnections(10);


        DockerClient dockerClient = DockerClientBuilder.getInstance(dockerClientConfig)
                .withDockerCmdExecFactory(dockerCmdExecFactory)
                .build();
        logger.info("docker version is " + dockerClient.versionCmd().exec().getVersion());
        FileInputStream fileInputStream;
        FileInputStream loadImageStream = null;
        try {

            // 获取镜像名
//            originalImageName = "ruoyi:1.2";
            fileInputStream = new FileInputStream(tarPath);
            originalImageName = UnCompress.getImageName(fileInputStream);
            fileInputStream.close();
            logger.info("originalImageName:" + originalImageName);
            //加载镜像
            logger.info("加载镜像");
            loadImageStream = new FileInputStream(tarPath);
            LoadImageCmd loadImageCmd = dockerClient.loadImageCmd(loadImageStream);
            loadImageCmd.exec();

            //push至镜像仓库
            PushImageResultCallback pushImageResultCallback = new PushImageResultCallback() {
                @Override
                public void onNext(PushResponseItem item) {
                    logger.info("id:" + item.getId() + " status: " + item.getStatus());
                    super.onNext(item);
                }

                @Override
                public void onComplete() {
                    logger.info("Image pushed completed!");
                    super.onComplete();
                }
            };
            if (!originalImageName.equalsIgnoreCase(this.imageName)) {
                String[] split = this.imageName.split(":");
                dockerClient.tagImageCmd(originalImageName, this.imageName, split[split.length - 1]).exec();
            }

            dockerClient.pushImageCmd(this.imageName)
                    .withAuthConfig(authConfig)
                    .exec(pushImageResultCallback)
                    .awaitSuccess();

            logger.info("push至docker镜像仓库后，删除本地load的镜像");
            dockerClient.removeImageCmd(originalImageName).exec();
            if (!originalImageName.equalsIgnoreCase(this.imageName)) {
                dockerClient.removeImageCmd(this.imageName).exec();
            }

            logger.info("本地镜像删除成功");
            result = true;
        } catch (IOException e) {
            result = false;
            e.printStackTrace();
            logger.warning("镜像格式错误！！");
        } catch (Exception e) {
            result = false;
            e.printStackTrace();
            logger.warning("上传Docker镜像失败");
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    logger.warning("文件流关闭失败");
                }
            }
            if (loadImageStream != null) {
                try {
                    loadImageStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    logger.warning("文件流关闭失败");
                }
            }

            // 删除tar包
            File file = new File(tarPath);
            file.delete();
        }
        long endTime = System.currentTimeMillis();
        logger.info("上传Docker镜像结束，用时：" + (endTime - beginTime) + "ms");
        return result;
    }


}
